package org.colour.amber.logic;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import java.util.Collection;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.colour.amber.rest.api.RestResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.async.DeferredResult;

/**
 * @author jasonfu
 * @date 2024/9/26 09:56
 */
@Slf4j
@Component
public class ConfigPublisher {

    /**
     * 用于绑定配置跟监听器之间的关系
     */
    private static final Multimap<String, DeferredResult<ResponseEntity<RestResponse<String>>>> CONFIG_CONTEXT =
            Multimaps.synchronizedSetMultimap(HashMultimap.create());

    /** 用于存储最新的配置 **/
    private static final Map<String, String> CONFIG_MAP = Maps.newConcurrentMap();

    public void pushConfig(String configId, String configValue) {
        CONFIG_MAP.put(configId, configValue);
    }

    public String getByConfigId(String configId) {
        return CONFIG_MAP.get(configId);
    }

    public void addConfigListener(
            String configId, DeferredResult<ResponseEntity<RestResponse<String>>> configListener) {
        CONFIG_CONTEXT.put(configId, configListener);
    }

    public void removeConfigListener(
            String configId, DeferredResult<ResponseEntity<RestResponse<String>>> configListener) {
        CONFIG_CONTEXT.remove(configId, configListener);
    }

    public void publishConfig(String configId, String configValue) {
        Collection<DeferredResult<ResponseEntity<RestResponse<String>>>> configListeners =
                CONFIG_CONTEXT.removeAll(configId);
        log.info("开始发布配置|configId={}|configValue={}|监听器数量={}", configId, configValue, configListeners.size());
        configListeners.forEach(
                configListener -> configListener.setResult(ResponseEntity.ok(RestResponse.success(configValue))));
    }

    @Async(value = "amberAsyncThreadPool")
    public void asyncPublishConfig(String configId, String configValue) {
        publishConfig(configId, configValue);
    }
}
